/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.diplomka.datalayer.daoimpl;

import cz.fi.muni.diplomka.common.enumeration.ColorType;
import cz.fi.muni.diplomka.common.enumeration.TitleType;
import cz.muni.fi.diplomka.datalayer.dao.PlayerDao;
import cz.muni.fi.diplomka.datalayer.entity.PlayerEntity;
import cz.muni.fi.diplomka.datalayer.util.DbConnector;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.neo4j.cypher.javacompat.ExecutionEngine;
import org.neo4j.cypher.javacompat.ExecutionResult;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Transaction;

/**
 *
 * @author Jakub Kutil
 */
public class PlayerDaoImpl implements PlayerDao {

    @Override
    public void addPlayer(PlayerEntity playerEntity) {
        if (playerEntity == null) {
            throw new IllegalArgumentException("Player Entity can not be null.");
        }

        GraphDatabaseService gds = DbConnector.getDBConnection();
        ExecutionEngine engine = DbConnector.getEngine();

        try (Transaction t = gds.beginTx()) {

            Map<String, Object> params = new HashMap<>();

            String query = "MATCH (Player:Player) RETURN max(Player.id)";

            Long key = new Long(0);
            ExecutionResult result = engine.execute(query);
            Iterator<Long> number = result.columnAs("max(Player.id)");
            while (number.hasNext()) {
                key = number.next();
            }

            if (key == null) {
                key = new Long(0);
            }
            playerEntity.setId(new Long(key + 1));

            params.put("id", playerEntity.getId());
            params.put("nickName", playerEntity.getNickName());
            params.put("hashedPassword", playerEntity.getHashedPassword());
            params.put("color", playerEntity.getColor().toString());
            params.put("title", playerEntity.getTitle().toString());

            query = "CREATE (Player:Player {id : {id}, nickName : {nickName}, hashedPassword : {hashedPassword}, color : {color}, title : {title}})";
            engine.execute(query, params);
            t.success();
        }
    }

    @Override
    public void editPlayer(PlayerEntity playerEntity) {
        if (playerEntity == null) {
            throw new IllegalArgumentException("Player Entity can not be null.");
        }

        GraphDatabaseService gds = DbConnector.getDBConnection();
        ExecutionEngine engine = DbConnector.getEngine();

        try (Transaction t = gds.beginTx()) {

            Map<String, Object> params = new HashMap<>();

            params.put("id", playerEntity.getId());
            params.put("nickName", playerEntity.getNickName());
            params.put("hashedPassword", playerEntity.getHashedPassword());
            params.put("color", playerEntity.getColor().toString());
            params.put("title", playerEntity.getTitle().toString());

            String query = "MATCH (Player:Player { id : {id} }) SET Player.nickName = {nickName}, Player.hashedPassword = {hashedPassword}, Player.color = {color}, Player.title = {title}";
            engine.execute(query, params);
            t.success();
        }
    }

    @Override
    public PlayerEntity findPlayerByNickName(String nickName) {
        if (nickName == null) {
            throw new IllegalArgumentException("Nickname can not be null.");
        }
        PlayerEntity playerEntity = new PlayerEntity();
        GraphDatabaseService gds = DbConnector.getDBConnection();
        ExecutionEngine engine = DbConnector.getEngine();


        try (Transaction t = gds.beginTx()) {
            Map<String, Object> params = new HashMap<>();

            params.put("nickName", nickName);

            String query = "MATCH (Player:Player { nickName: {nickName} }) RETURN Player";
            ExecutionResult result = engine.execute(query, params);

            Iterator<Node> players = result.columnAs("Player");
            while (players.hasNext()) {
                Node node = players.next();
                playerEntity.setId(new Long(node.getProperty("id").toString()));
                playerEntity.setNickName(node.getProperty("nickName").toString());
                playerEntity.setHashedPassword(node.getProperty("hashedPassword").toString());
                playerEntity.setColor(ColorType.valueOf(node.getProperty("color").toString()));
                playerEntity.setTitle(TitleType.valueOf(node.getProperty("title").toString()));
            }

            t.success();
        }
        return playerEntity;
    }

    @Override
    public PlayerEntity findPlayerById(Long id) {
        if (id == null) {
            throw new IllegalArgumentException("Id can not be null.");
        }
        PlayerEntity playerEntity = new PlayerEntity();
        GraphDatabaseService gds = DbConnector.getDBConnection();
        ExecutionEngine engine = DbConnector.getEngine();


        try (Transaction t = gds.beginTx()) {
            Map<String, Object> params = new HashMap<>();

            params.put("id", id);

            String query = "MATCH (Player:Player { id: {id} }) RETURN Player";
            ExecutionResult result = engine.execute(query, params);
            Iterator<Node> players = result.columnAs("Player");
            while (players.hasNext()) {
                Node node = players.next();
                playerEntity.setId(new Long(node.getProperty("id").toString()));
                playerEntity.setNickName(node.getProperty("nickName").toString());
                playerEntity.setHashedPassword(node.getProperty("hashedPassword").toString());
                playerEntity.setColor(ColorType.valueOf(node.getProperty("color").toString()));
                playerEntity.setTitle(TitleType.valueOf(node.getProperty("title").toString()));
            }
            t.success();
        }
        return playerEntity;
    }
}